package com.tau.egonetwork.facebook;

import org.json.JSONArray;
import org.json.JSONObject;

import com.tau.egonetwork.net.IProfileResponse;
import com.tau.egonetwork.net.IProfileResponseProgress;
import com.tau.egonetwork.profiles.FriendsList;
import com.tau.egonetwork.profiles.Group;
import com.tau.egonetwork.profiles.GroupsList;
import com.tau.egonetwork.profiles.Profile;
import com.tau.egonetwork.profiles.ProfileFile;
import com.tau.egonetwork.profiles.ProfileFile.SocialNetworks;

public class FacebookResponse implements IProfileResponse<Long> {

	private static final String FACEBOOK_FIELD_ID = "id";
	private static final String FACEBOOK_FIELD_NAME = "name";
	private static final String FACEBOOK_FIELD_GENDER = "gender";
	private static final String FACEBOOK_FIELD_LOCATION = "location";
	
	private static final String FACEBOOK_ARRAY_FRIENDS = "friends";
	private static final String FACEBOOK_ARRAY_MUTUALFRIENDS = "mutualfriends";
	private static final String FACEBOOK_ARRAY_WORK = "work";
	private static final String FACEBOOK_ARRAY_FRIENDLISTS = "friendlists";
	private static final String FACEBOOK_ARRAY_MEMBERS = "members";
	
	private IFacebookResponseProgress responseProgress;
	
	private Profile<Long> createBasicProfile(JSONObject json, boolean isMain) {
		
		long id = json.getLong(FACEBOOK_FIELD_ID);
		String name = json.getString(FACEBOOK_FIELD_NAME);
		Profile<Long> profile;
		if(isMain) {
			profile = new FacebookMainProfile(id, name);
		} else {
			profile = new FacebookFriendProfile(id, name);
		}
		
		if (json.has(FACEBOOK_FIELD_GENDER))
			profile.setGender(json.getString(FACEBOOK_FIELD_GENDER));
		if (json.has(FACEBOOK_FIELD_LOCATION))
			profile.setLocation(json.getJSONObject(FACEBOOK_FIELD_LOCATION).
					getString(FACEBOOK_FIELD_NAME));
		
		extractWorkLocation(profile, json);
		
		return profile;
	}
	
	private void extractWorkLocation(Profile<Long> p, JSONObject json) {
		if (json.has(FACEBOOK_ARRAY_WORK)) {
			JSONArray work = json.getJSONArray(FACEBOOK_ARRAY_WORK);
			if (work.length() > 0) {
				JSONObject currentWork = (JSONObject) work.get(0);
				if (currentWork.has(FACEBOOK_FIELD_LOCATION)) {
					JSONObject workLocation = currentWork.getJSONObject(FACEBOOK_FIELD_LOCATION);
					p.setWorkLocation(workLocation.getString(FACEBOOK_FIELD_NAME));
				}
			}
		}
	}
	
	@Override
	public FacebookMainProfile parseJSONResponse(String response) {
		
		responseProgress.onResponseReceived();
		
		JSONObject json = new JSONObject(response.toString());
		
		FacebookMainProfile profile = (FacebookMainProfile) createBasicProfile(json, true);
		
		responseProgress.onProfileExtracted(profile.getName());
		
		FriendsList<Long> flist = profile.createFriendsList();
		
		//if user has no friends (then no groups as well), stop here:
		if (!json.has(FACEBOOK_ARRAY_FRIENDS))
			return profile;
		
		JSONArray friends = json.getJSONObject(FACEBOOK_ARRAY_FRIENDS).getJSONArray(ARRAY_DATA);
		int friends_size = friends.length();
		
		responseProgress.onStartReadingFriends(friends_size);
		
		/* first create the user's friends' list : */
		for (int i = 0; i < friends_size; i++) {
			responseProgress.onReadFriend(i);
			JSONObject friend = (JSONObject)friends.get(i);
			FacebookFriendProfile friendFB = (FacebookFriendProfile) createBasicProfile(friend, false);
			flist.add(friendFB);
			if (friend.has(FACEBOOK_ARRAY_MUTUALFRIENDS)) {
				friendFB.createFriendsList();
			}
		}
				
		/* now, for each friend, create the list of mutual friends: */
		for (int i = 0; i < friends_size; i++) {
			
			responseProgress.onReadMutualFriends(i);
			
			//if there are no mutual friends, continue to next friend:
			FriendsList<Long> friendFB = flist.get(i).getFriendsList();
			if (friendFB == null)
				continue;
			
			JSONArray mutualfriends = ((JSONObject)friends.get(i)).getJSONObject(FACEBOOK_ARRAY_MUTUALFRIENDS).getJSONArray(ARRAY_DATA);
			int mutualfriends_size = mutualfriends.length();
			for (int j = 0; j < mutualfriends_size; j++) {
				Profile<Long> mutualFriend = flist.get(((JSONObject)mutualfriends.get(j)).getLong(FACEBOOK_FIELD_ID));
				if (mutualFriend != null)
					friendFB.add(mutualFriend);
			}
			
		}
				
		/* if user is a member of any group, create said group: */
		if (json.has("friendlists") && flist != null) {
			
			GroupsList<Long> groupslist = profile.createGroupsList();
			JSONArray groups = json.getJSONObject(FACEBOOK_ARRAY_FRIENDLISTS).getJSONArray(ARRAY_DATA);
			int groups_size = groups.length();
			
			responseProgress.onReadGroups(groups_size);
			
			for (int i = 0; i < groups_size; i++) {
				JSONObject group = (JSONObject) groups.get(i);
				Group<Long> g = new Group<Long>(group.getString(FACEBOOK_FIELD_NAME));
				if (group.has(FACEBOOK_ARRAY_MEMBERS)) {
					responseProgress.onReadGroupsFriend(i);
					JSONArray members = group.getJSONObject(FACEBOOK_ARRAY_MEMBERS).getJSONArray(ARRAY_DATA);
					int members_size = members.length();
					for (int j = 0; j < members_size; j++) {
						Profile<Long> member = flist.get(((JSONObject)members.get(j)).getLong(FACEBOOK_FIELD_ID));
						if (member != null)
							g.add(member);
					}
				}
				groupslist.add(g);
			}
		}
		
		responseProgress.onSaveToFile();
		
		ProfileFile.saveToFile(SocialNetworks.Facebook, profile);
		
		return profile;
	}

	@Override
	public void setIProfileProgress(IProfileResponseProgress progress) {
		responseProgress = (IFacebookResponseProgress)progress;
	}
	
}
